home *** CD-ROM | disk | FTP | other *** search
- #pragma inline
-
- /*********************************/
- /* */
- /* CONFIG.C - by Mike Klein */
- /* */
- /* ver 2.0 */
- /* */
- /*-------------------------------*/
- /* */
- /* A routine to show computer's */
- /* configuration and optionally */
- /* alter the parent environment */
- /* SETting variables based upon */
- /* the status of/equipment found */
- /* in the computer being used. */
- /* */
- /*-------------------------------*/
- /* */
- /* FINISHED: 07/13/89 */
- /* */
- /*********************************/
-
- /**************************************************/
- /* */
- /* NOTE: Users experiencing difficulty compiling */
- /* will probably want to remove the references to */
- /* in-line assembly code. This is used only in */
- /* the CPU determining function. Also remove the */
- /* #pragma inline statement at the top of the */
- /* listing. Remember to compile with byte */
- /* alignment. The following are some function */
- /* definitions that your compiler may not support */
- /* directly. Use these defines to include them */
- /* if that is the case. */
- /* */
- /**************************************************/
-
- /*
- #define MK_FP(seg,ofs) ((void far *) \
- (((unsigned long)(seg) << 16) | (unsigned)(ofs)))
- #define poke(a, b, c) (*((int far *) MK_FP((a), (b))) = (int) (c))
- #define pokeb(a, b, c) (*((char far *) MK_FP((a), (b))) = (char) (c))
- #define peek(a, b) (*((int far *) MK_FP((a), (b))))
- #define peekb(a, b) (*((char far *) MK_FP((a), (b))))
- */
-
-
- /*****************/
- /* */
- /* INCLUDE FILES */
- /* */
- /*****************/
-
- #include <string.h>
- #include <dos.h>
- #include <stdio.h>
- #include <stdlib.h>
-
-
- /***********/
- /* */
- /* DEFINES */
- /* */
- /***********/
-
- #define VERSION 2.0
- #define TRUE 1
- #define FALSE 0
- #define VOID void
-
- #define intvideo(regs) int86(0x10, regs, regs)
- #define intmouse(regs) int86(0x33, regs, regs)
-
-
- /*************/
- /* */
- /* TYPEDEF'S */
- /* */
- /*************/
-
- typedef signed char BOOLEAN;
- typedef unsigned char BYTE;
- typedef signed char CHAR;
- typedef signed int INT;
- typedef unsigned int COUNTER;
-
- typedef unsigned int SEGMENT;
- typedef unsigned int LENGTH;
-
- CHAR far *par_env; /* Pointer to parent environment */
- LENGTH par_env_len; /* Length of parent environment */
-
-
- /****************/
- /* */
- /* DECLARATIONS */
- /* */
- /****************/
-
- VOID put_par_env(CHAR *env_var, CHAR *env_text);
- VOID del_par_env(CHAR *env_var);
-
-
- /********/
- /* */
- /* MAIN */
- /* */
- /********/
-
- VOID main(COUNTER argc, CHAR *argv[])
- {
- CHAR *class; /* Like model, but only (PC/AT) */
- CHAR conv[4]; /* Conventional memory size */
- CHAR *cpu; /* CPU type (808x, 80286, 80386) */
- CHAR date[9]; /* System date */
- CHAR *exp; /* Expanded memory? (YES/NO) */
- CHAR *ext; /* Extended memory? (YES/NO) */
- CHAR *fpu; /* FPU present? (YES/NO) */
- CHAR *mca; /* Micro Channel? (YES/NO) */
- CHAR *mode; /* Video mode (COLOR/MONOCHROME) */
- CHAR *model; /* Model (PC/XT/XT-286/AT/25/30/50 */
- /* 60/70/80) */
- CHAR *mouse; /* Mouse present? (YES/NO) */
- CHAR rom_date[9]; /* Computer's rom date */
- CHAR *ps2; /* PS/2 system? (YES/NO) */
- CHAR version[5]; /* DOS version (2.0, 3.3, etc.) */
- CHAR *video; /* Video adapter (MDA, HERC, CGA, */
- /* EGA, PGA, VGA, */
- /* MCGA) */
-
- BYTE byte;
- BYTE main;
- BYTE sub;
- BYTE features;
-
- CHAR far *far_ptr;
- SEGMENT far *seg_ptr;
- CHAR *emm_id;
-
- int env_set = FALSE;
-
- COUNTER i;
-
- union REGS regs;
- struct SREGS sregs;
-
- struct date system_date;
-
- /* Structs for PSP and DOS Memory Control Block (MCB) */
-
- typedef struct
- {
- CHAR misc1[22];
- SEGMENT par_seg;
- CHAR misc2[20];
- SEGMENT env_seg;
- } PSP;
-
- /* Compile with byte alignment */
-
- typedef struct
- {
- CHAR status; /* Block is in chain or not */
- SEGMENT owner_psp; /* PSP segment of block's owner */
- LENGTH size; /* Size (in paragraphs) of block */
- } MCB;
-
- MCB far *config_mcb; /* config.sys MCB */
- MCB far *command_mcb; /* command.com MCB */
- MCB far *env_mcb; /* environments MCB */
- PSP far *command_psp; /* command.com PSP */
-
-
- /***************************/
- /* */
- /* COMMAND LINE PARAMETERS */
- /* */
- /***************************/
-
- if(argc > 1)
- if(!strcmp(argv[1], "/e") || !strcmp(argv[1], "/E"))
- env_set = TRUE;
- else
- {
- puts("\nERROR: Bad parameter...");
- exit(-1);
- }
- else
- env_set = FALSE;
-
-
- /***************************/
- /* */
- /* FIND PARENT ENVIRONMENT */
- /* */
- /***************************/
-
- regs.x.ax = 0x5200;
- intdosx(®s, ®s, &sregs);
- seg_ptr = MK_FP(sregs.es, regs.x.bx - 2);
-
- config_mcb = MK_FP(*seg_ptr, 0);
-
- command_psp = MK_FP(FP_SEG(config_mcb) + config_mcb->size + 2, 0);
-
- if(command_psp->env_seg == 0)
- {
- /* Environment is in block after parent program */
- command_mcb = MK_FP(FP_SEG(config_mcb) + config_mcb->size + 1, 0);
- par_env = MK_FP(FP_SEG(command_mcb) + command_mcb->size + 2, 0);
- }
- else /* We have pointer to environment */
- par_env = MK_FP(command_psp->env_seg, 0);
-
- /* MCB of environment is 1 segment lower */
-
- env_mcb = MK_FP(FP_SEG(par_env) - 1, 0);
-
- par_env_len = env_mcb->size * 16; /* Save len of environment */
-
- printf("\n\nSYSTEM CONFIGURATION v%1.1f\n", VERSION);
- puts("=========================");
-
-
- /*************/
- /* */
- /* MODEL/MCA */
- /* */
- /*************/
-
- byte = peekb(0xf000, 0xfffe); /* Get model byte */
- mca = "NO";
- ps2 = "NO";
-
- switch(byte)
- {
- case 0xff :
- model = "PC";
- break;
- case 0xfe :
- case 0xfb :
- model = "XT";
- break;
- case 0xfc :
- case 0xfa :
- case 0xf8 :
- regs.x.ax = 0xc000; /* Get the system environment info */
- int86x(0x15, ®s, ®s, &sregs);
- main = peekb(sregs.es, regs.x.bx + 2);
- if(byte != main) /* Some AT's don't support this */
- { /* function so let's abort */
- model = "AT";
- break;
- }
- sub = peekb(sregs.es, regs.x.bx + 3);
- features = peekb(sregs.es, regs.x.bx + 5);
- if(features & 0x02)
- mca = "YES";
- switch(main)
- {
- case 0xfc :
- switch(sub)
- {
- case 0x02 :
- model = "XT286";
- break;
- case 0x04 :
- model = "50";
- ps2 = "YES";
- break;
- case 0x05 :
- model = "60";
- ps2 = "YES";
- break;
- case 0x00 :
- case 0x01 :
- default :
- model = "AT";
- break;
- }
- break;
- case 0xf8 :
- ps2 = "YES";
- switch(sub)
- {
- case 0x00 :
- case 0x01 :
- model = "80";
- break;
- case 0x04 :
- case 0x09 :
- default :
- model = "70";
- break;
- }
- break;
- case 0xfa :
- ps2 = "YES";
- switch(sub)
- {
- case 0x01 :
- model = "25";
- break;
- case 0x00 :
- default :
- model = "30";
- break;
- }
- break;
- default :
- model = "N/A";
- break;
- }
- break;
- default :
- model = "N/A";
- break;
- }
- printf("MODEL.....%s\n", model);
- printf("PS/2......%s\n", ps2);
- printf("MCA.......%s\n", mca);
- if(env_set)
- {
- put_par_env("MODEL", model);
- put_par_env("PS/2", ps2);
- put_par_env("MCA", mca);
- }
-
-
- /************/
- /* */
- /* CPU TYPE */
- /* */
- /************/
-
- asm pushf
- asm xor ax,ax
- asm push ax
- asm popf
- asm pushf
- asm pop ax
- asm and ax,0f000h
- asm cmp ax,0f000h
- asm jz is_808x
-
- asm mov ax,07000h /* If we can't set bits 12-14 then */
- asm push ax /* CPU is 80286 */
- asm popf
- asm pushf
- asm pop ax
- asm and ax,07000h
- asm jz is_80286
-
- is_80386 :
- asm mov ax,386h
- asm jmp done
-
- is_80286 :
- asm mov ax,286h
- asm jmp done
-
- is_808x :
- asm mov ax,86h
-
- done:
- asm popf
-
- switch(_AX)
- {
- case 0x386 :
- cpu = "80386";
- class = "AT";
- break;
- case 0x286 :
- cpu = "80286";
- class = "AT";
- break;
- case 0x86 :
- cpu = "808x";
- class = "PC";
- break;
- default :
- cpu = "N/A";
- break;
- }
- printf("CPU.......%s\n", cpu);
- printf("CLASS.....%s\n", class);
- if(env_set)
- {
- put_par_env("CPU", cpu);
- put_par_env("CLASS", class);
- }
-
-
- /**************/
- /* */
- /* MATH CHIP? */
- /* */
- /**************/
-
- int86(0x11, ®s, ®s); /* Get BIOS equip word for FPU */
- fpu = (regs.x.ax & 0x02) ? "YES" : "NO";
-
- printf("FPU.......%s\n", fpu);
- if(env_set)
- put_par_env("FPU", fpu);
-
-
- /************/
- /* */
- /* GET DATE */
- /* */
- /************/
-
- regs.x.ax = 0x0400;
- int86(0x1a, ®s, ®s);
- sprintf(date, "%02x/%02x/%02x", regs.h.dh, regs.h.dl, regs.h.cl);
-
- printf("DATE......%s\n", date);
- if(env_set)
- put_par_env("DATE", date);
-
-
- /***********************/
- /* */
- /* CONVENTIONAL MEMORY */
- /* */
- /***********************/
-
- int86(0x12, ®s, ®s); /* INT 0x12 returns conv memory */
- if((regs.x.ax % 2) != 0) /* Some systems report 1K less */
- ++regs.x.ax; /* than actual, so we compensate */
- sprintf(conv, "%u", regs.x.ax);
-
- printf("CONV......%s\n", conv);
- if(env_set)
- put_par_env("CONV", conv);
-
-
- /*******************/
- /* */
- /* EXPANDED MEMORY */
- /* */
- /*******************/
-
- emm_id = "EMMXXXX0";
-
- regs.x.ax = 0x3567;
- intdosx(®s, ®s, &sregs);
- far_ptr = MK_FP(sregs.es, 10);
-
- for(i=0; i < 8; i++)
- {
- if(far_ptr[i] != emm_id[i])
- {
- exp = "NO";
- break;
- }
- }
- if(i == 8)
- {
- exp = "YES";
- regs.h.ah = 0x42;
- int86(0x67, ®s, ®s);
- }
-
- printf("EXP.......%s", exp);
- if(i == 8)
- printf(" (%dK)\n", regs.x.bx * 16);
- else
- printf("\n");
- if(env_set)
- put_par_env("EXP", exp);
-
-
- /*******************/
- /* */
- /* EXTENDED MEMORY */
- /* */
- /*******************/
-
- /* This code must follow the CPU code */
-
- if(! strcmp(class, "AT"))
- {
- regs.x.ax = 0x8800;
- int86(0x15, ®s, ®s);
- i = regs.x.ax;
- if((i != 0x8800) && (i != 0x0000))
- ext = "YES";
- else
- ext = "NO";
- }
- else
- ext = "NO";
-
- printf("EXT.......%s", ext);
- if(!strcmp(ext, "YES"))
- printf(" (%dK)\n", i);
- else
- printf("\n");
- if(env_set)
- put_par_env("EXT", ext);
-
-
- /**********/
- /* */
- /* MOUSE? */
- /* */
- /**********/
-
- regs.x.ax = 0x00; /* Mouse Func 0 - initialize */
- intmouse(®s);
- if(regs.x.ax)
- mouse = "YES";
- else
- mouse = "NO";
-
- printf("MOUSE.....%s\n", mouse);
- if(env_set)
- put_par_env("MOUSE", mouse);
-
-
- /************/
- /* */
- /* ROM DATE */
- /* */
- /************/
-
- far_ptr = MK_FP(0xf000, 0xfff5); /* Make pointer to address */
- /* of computer's rom date */
- if(far_ptr[2] == far_ptr[5])
- {
- for(i=0; i<8; ++i)
- rom_date[i] = far_ptr[i]; /* Make string from far_ptr */
- rom_date[i] = '\0';
- }
- else
- strcpy(rom_date, "N/A");
-
- printf("ROM DATE..%s\n", rom_date);
- if(env_set)
- put_par_env("ROM_DATE", rom_date);
-
-
- /**************/
- /* */
- /* VIDEO MODE */
- /* */
- /**************/
-
- regs.x.ax = 0x0f00;
- intvideo(®s);
- switch(regs.h.al)
- {
- case 0x00 :
- case 0x02 :
- case 0x07 :
- mode = "MONOCHROME";
- break;
- default :
- mode = "COLOR";
- break;
- }
-
- printf("MODE......%s\n", mode);
- if(env_set)
- put_par_env("MODE", mode);
-
-
- /*****************/
- /* */
- /* VIDEO ADAPTER */
- /* */
- /*****************/
-
- regs.x.ax = 0x1a00; /* If function supported (_AL=0x1A) */
- intvideo(®s);
- if(regs.h.al == 0x1a)
- {
- switch(regs.h.bl)
- {
- case 0x01 :
- video = "MDA";
- break;
- case 0x02 :
- video = "CGA";
- break;
- case 0x04 :
- case 0x05 :
- video = "EGA";
- break;
- case 0x06 :
- video = "PGA";
- break;
- case 0x07 :
- case 0x08 :
- video = "VGA";
- break;
- case 0x0a :
- case 0x0b :
- case 0x0c :
- video = "MCGA";
- break;
- default :
- video = "VGA";
- break;
- }
- }
- else
- {
- regs.h.ah = 0x12; /* Get config info for EGA/VGA */
- regs.h.bl = 0x10;
- intvideo(®s);
- if(regs.h.bl != 0x10)
- video = "EGA"; /* BL changed? Then EGA */
- else
- {
- regs.h.ah = 0x0f; /* See if color or mono */
- intvideo(®s);
- if(regs.h.al == 7)
- { /* Read CRT status port, mask bit 7 */
- byte = inport(0x3ba) & 0x80;
- for(i = 0; i < 32767; i++) /* Will bit 7 change? */
- if(byte != inport(0x3ba) & 0x80)
- break; /* If bit 7 didn't change, then MDA */
- video = (i != 32767) ? "HERC" : "MDA";
- }
- else
- video = "CGA";
- }
- }
- printf("VIDEO.....%s\n", video);
- if(env_set)
- put_par_env("VIDEO", video);
-
-
- /***************/
- /* */
- /* DOS VERSION */
- /* */
- /***************/
-
- regs.h.ah = 0x30; /* INT 0x21 FUNC 0x30 to get DOS */
- intdos(®s, ®s); /* version number */
-
- sprintf(version, "%u.%u", (unsigned) regs.h.al, (unsigned) regs.h.ah);
- printf("VERSION...%s\n", version);
- if(env_set)
- put_par_env("VERSION", version);
-
- puts("=========================\n");
-
- }
-
-
- /***************/
- /* */
- /* PUT_PAR_ENV */
- /* */
- /***************/
-
- VOID put_par_env(CHAR *env_var, CHAR *env_text)
- {
-
- CHAR far *far0;
- LENGTH len;
- CHAR env_str[256];
- CHAR *str;
-
- strcpy(env_str, env_var); /* Create environment string */
- strcat(env_str, "=");
- strcat(env_str, env_text);
- strupr(env_str);
-
- del_par_env(env_var); /* Delete variable of same name */
-
- /* Find end of environment by looking for 2 NULLS */
- for(far0 = par_env, len = 0; !(!*far0 && !*(far0+1)); ++far0, ++len)
- ;
-
- len = par_env_len - (len + 2); /* Get free space in environment */
-
- if(len < strlen(env_str) + 1)
- { /* If out of room, return error */
- puts("\nERROR: Out of environment space...\n");
- exit(-1);
- }
-
- str = env_str;
-
- for(++far0; *str; *far0++ = *str++) /* Copy str to end of par env */
- ;
-
- *far0 = 0; /* End env with 2 nulls */
- ++far0;
- *far0 = 0;
-
- }
-
-
- /***************/
- /* */
- /* DEL_PAR_ENV */
- /* */
- /***************/
-
- VOID del_par_env(CHAR *env_var)
- {
-
- CHAR far *far1; /* Beginning of next variable */
- CHAR far *far2; /* Beginning of the variable */
- CHAR *str; /* env_var ptr used in search */
-
- int found = FALSE; /* End of search flag */
-
- far1 = par_env;
-
- while(*far1 && !found)
- { /* Find start of variable to delete */
- str = env_var;
- far2 = far1;
- for(;(*far1 == *str) && (*far1 != '=') && *far1 && *str; ++far1, ++str)
- ;
- if((!*str) && (*far1 == '='))
- found = TRUE; /* We found it! */
- for(; *far1; ++far1)
- ;
- ++far1;
- }
-
- if(!*far1 && !found) /* Find env_var? */
- return; /* No, we didn't */
-
- /* Shift environment down, to cover env_var */
-
- for(; !(!*far1 && !*(far1+1)); *far2++ = *far1++)
- ;
-
- *far2 = 0; /* End env with 2 nulls */
- ++far2;
- *far2 = 0;
-
- }
-